package cn.jimmie.learn.viewArt.weight;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import cn.jimmie.learn.viewArt.R;

/**
 * function :
 *
 * <p> Create Time: 2018年12月23日 15:41 </p>
 * <p> @author Jimmie.Qian  </p>
 */
public class CircleLoadingView extends View implements ValueAnimator.AnimatorUpdateListener {
    // √2/2的近似值
    private static final float ROOT2 = 0.70710678118f;

    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
    private ValueAnimator mAnimator = ValueAnimator.ofInt(0, Integer.MAX_VALUE);
    private float mDotRadius;
    private P[] mDots;
    private int mOffset = 0;
    private int mPreOffset = -1;

    private float mLoadUnit = 1000;


    public CircleLoadingView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CircleLoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        int[] attrsArray = new int[]{android.R.attr.layout_width, android.R.attr.layout_height};
        TypedArray sta = context.obtainStyledAttributes(attrs, attrsArray);
        float width = sta.getDimension(0, ViewGroup.LayoutParams.MATCH_PARENT);
        float height = sta.getDimension(1, ViewGroup.LayoutParams.MATCH_PARENT);
        sta.recycle();

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CircleLoadingView);
        float padding = ta.getDimension(R.styleable.CircleLoadingView_android_padding, 0);
        float realH = (height - padding * 2);
        float dDotRadius = realH / 8 / 8;
        mDotRadius = ta.getDimension(R.styleable.CircleLoadingView_dotRadius, dDotRadius);
        float radius = ta.getDimension(R.styleable.CircleLoadingView_radius, realH / 2 - mDotRadius * 8);
        int color = ta.getColor(R.styleable.CircleLoadingView_dotColor, Color.BLACK);
        ta.recycle();

        mPaint.setColor(color);
        mDots = create8Dots(width / 2, height / 2, radius);

        mAnimator.setInterpolator(new LinearInterpolator());
        mAnimator.setDuration(Integer.MAX_VALUE);
        mAnimator.addUpdateListener(this);
        mAnimator.start();
    }

    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float value = ((int) animation.getAnimatedValue() % mLoadUnit);
        mOffset = (int) (value / (mLoadUnit / 8));
        // 性能优化, 避免不必要的绘制
        if (mOffset != mPreOffset) {
            mPreOffset = mOffset;
            invalidate();
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        for (int i = 0; i < mDots.length; i++) {
            P dot = mDots[(i + mOffset) % 8];
            canvas.drawCircle(dot.x, dot.y, mDotRadius * (i + 1), mPaint);
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        mAnimator.cancel();
        super.onDetachedFromWindow();
    }

    public void setSpeed(float speed) {
        mLoadUnit *= speed;
    }

    @Override
    public void setVisibility(int visibility) {
        mAnimator.cancel();
        if (visibility == View.VISIBLE) {
            mAnimator.start();
        }
        super.setVisibility(visibility);
    }

    /**
     * 获取8个圆心的位置
     *
     * @param x,y 圆心坐标
     * @param r   大圆半径
     */
    private static P[] create8Dots(float x, float y, float r) {
        return new P[]{
                newP(x, y - r),
                newP(x + ROOT2 * r, y - ROOT2 * r),
                newP(x + r, y),
                newP(x + ROOT2 * r, y + ROOT2 * r),
                newP(x, y + r),
                newP(x - ROOT2 * r, y + ROOT2 * r),
                newP(x - r, y),
                newP(x - ROOT2 * r, y - ROOT2 * r)
        };
    }

    private static P newP(float x, float y) {
        return new P(x, y);
    }


    /**
     * 八个点的圆心坐标
     */
    private static class P {
        P(float x, float y) {
            this.x = x;
            this.y = y;
        }

        float x;
        float y;
    }
}
